from __future__ import print_function

from kivy.properties import ObjectProperty, ListProperty,\
    NumericProperty, BooleanProperty
from kivy.uix.widget import Widget

import goblinoid.config.feedsections as fs
from goblinoid.services.pumpthreads import FeedThread
from thread_queue import ThreadQueue


class FeedService(Widget):
    pump = ObjectProperty()
    pump_service = ObjectProperty()
    feed_data = ListProperty([])
    activity_list = ListProperty([])
    feed_index = NumericProperty(0)
    batch_size = NumericProperty(10)
    already_prefetching = BooleanProperty(False)
    already_refreshing = BooleanProperty(False)
    prefetch_thread = ObjectProperty()
    refresh_thread = ObjectProperty()
    refresh_callback = ObjectProperty()
    prefetch_callback = ObjectProperty()

    profile_manager = ObjectProperty()
    activity_manager = ObjectProperty()

    def __init__(self, **kwargs):
        super(FeedService, self).__init__(**kwargs)
        self.prefetch_queue = ThreadQueue(self.update_feed)
        self.refresh_queue = ThreadQueue(self.refresh_feed)
        self.feed_data_generator = fs.mg_activity_dict

    def fetch_feed_data(self, callback):
        if len(self.activity_list) > 0:
            callback(self.update_feed_data())
        else:
            self.start_refresh(callback)

    def start_prefetch(self, callback):
        self.prefetch_callback = callback
        if not self.already_prefetching and not self.already_refreshing:
            print ('updating feed')
            self.already_prefetching = True
            self.feed_data = []
            try:
                self.prefetch_thread = FeedThread(
                    self.prefetch_queue,
                    self.pump.me.inbox.major,
                    self.feed_index,
                    self.batch_size)
                self.prefetch_thread.start()
                self.feed_index += self.batch_size
            except KeyError:
                self.refresh_queue.put('error', None)

    def start_refresh(self, callback):
        self.refresh_callback = callback
        if self.already_refreshing:
            return False
        if self.already_prefetching:
            self.prefetch_thread.is_running = False
            # note we may want to clear out the prefetch_queue at this point
            self.already_prefetching = False
        print ('refreshing feed')
        self.already_refreshing = True
        self.feed_index = 0
        self.feed_data = []
        self.activity_list = []
        self.pump_service.comment_modals.clear()
        self.activity_manager.clear_activities()
        try:
            self.refresh_thread = FeedThread(
                self.refresh_queue,
                self.pump.me.inbox.major,
                self.feed_index,
                self.batch_size)
            self.refresh_thread.start()
            self.feed_index += self.batch_size
        except KeyError:
            self.refresh_queue.put('error', None)
        return True

    def update_feed(self):
        while True:
            if self.prefetch_queue.empty():
                break
            index, activity = self.prefetch_queue.get()
            if index == 'none':
                self.already_prefetching = False
                self.start_prefetch(self.prefetch_callback)
            elif index == 'done':
                self.prefetch_callback(self.feed_data)
                self.feed_data = []
                self.already_prefetching = False
                break
            elif index == 'error':
                self.prefetch_callback(None)
                self.feed_data = []
                self.already_prefetching = False
                break
            else:
                self.activity_manager.add_activity(activity)
                self.activity_list.append(activity.id)
                activity_data = self.feed_data_generator(
                    activity, int(index))
                self.feed_data.extend(activity_data)
                self.add_profiles_from_activity(activity)

    def add_profiles_from_activity(self, activity):
        self.profile_manager.add_profile(activity.actor)
        for comment in activity.obj.comments:
            self.profile_manager.add_profile(comment.author)

    def refresh_feed(self):
        while True:
            if self.refresh_queue.empty():
                break
            index, activity = self.refresh_queue.get()
            if index == 'none':
                self.already_refreshing = False
                self.start_prefetch(self.refresh_callback)
            elif index == 'done':
                self.already_refreshing = False
                self.refresh_callback(self.feed_data)
                self.profile_manager.on_refresh()
                break
            elif index == 'error':
                self.already_refreshing = False
                self.refresh_callback(None)
                self.feed_data = []
                break
            else:
                self.activity_manager.add_activity(activity)
                self.activity_list.append(activity.id)
                activity_data = self.feed_data_generator(
                    activity, int(index))
                self.feed_data.extend(activity_data)
                self.add_profiles_from_activity(activity)

    def update_feed_data(self):
        updated_data = []
        for activity_id in self.activity_list:
            activity_service = self.activity_manager.get_activity_service(
                activity_id)
            activity_data = activity_service.get_activity_data()
            updated_data.extend(activity_data)
        return updated_data

    def update_feed_data_in_background(self, callback):
        if not self.already_refreshing:
            return self.update_feed_data()
        else:
            self.refresh_callback = callback
